﻿
Imports System.IO
Imports System.Threading
Imports std

Public MustInherit Class loghandler
    Protected MustOverride Sub initial()
    Protected MustOverride Sub oneline(ByRef log As String, ByRef casename As String)

    Protected name As String = Nothing
    Protected backupConfignaming As String = Nothing
    Protected caseConfigNaming As String = configNaming.loghandler.case
    Protected filterConfigNaming As String = configNaming.loghandler.filter
    Protected multimatchConfigNaming As String = configNaming.loghandler.multimatch
    Protected multimatch As Boolean = False
    Private casenames As vector(Of String) = Nothing
    Private filters As vector(Of String) = Nothing
    Private config As pointer(Of configParser) = Nothing
    Private mutex As Mutex = Nothing

    Public Sub oneline(ByRef log As String)
        assert(casenames.size() = filters.size() _
               , "initial failed? casenames.size() should be the same as filters.size()")

        Dim i As Int64
        For i = 0 To filters.size() - 1
            If fitfilter(filters(i), log) Then
                assert(mutex.WaitOne(), "cannot lock mutex when call oneline(log, casename)")
                oneline(log, casenames(i))
                mutex.ReleaseMutex()
                If Not multimatch Then
                    Exit For
                End If
            End If
        Next
    End Sub

    Public Function defaultOutputfile(Optional ByRef defaultOutputpath As String = Nothing) As String
        Return configParameter(Of String)(configNaming.counter.outputpath, defaultOutputpath) _
                + filesystem.directorySeperator + name + character.underline _
                + shortTime(character.underline, character.minusSign, character.minusSign)
    End Function

    Protected Shared Function createWriter(ByRef writer As TextWriter, ByRef filename As String) As Boolean
        Dim dir As String = parentpath(filename)
        If Not Directory.Exists(dir) Then
            Directory.CreateDirectory(dir)
        End If
        Try
            writer = New StreamWriter(New FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.Read))
        Catch ex As Exception
            raiseError("cannot create StreamWriter instance, " + ex.Message, errorHandle.errorType.system)
            Return False
        End Try

        Return True
    End Function

    Protected Function configParameter(Of T)(ByRef key As String, Optional ByRef defaultValue As T = Nothing) As T
        assert(Not isemptystring(backupConfignaming), "should set backupConfignaming when configParamter.")
        Dim rtn As T = Nothing
        If (+config).getparameter(name, key, rtn, defaultValue) Then
            Return rtn
        End If

        If (+config).getparameter(backupConfignaming, key, rtn, defaultValue) Then
            Return rtn
        End If

        Return defaultValue
    End Function

    Protected Function configlist(Of valueT)(ByRef key As String, ByRef values As vector(Of valueT)) As Boolean
        assert(Not isemptystring(backupConfignaming), "should set backupConfignaming when configlist.")
        If (+config).readlist(name, key, values) Then
            Return True
        End If

        If (+config).readlist(backupConfignaming, key, values) Then
            Return True
        End If

        Return False
    End Function

    Public Sub New()
        casenames = New vector(Of String)
        filters = New vector(Of String)
        mutex = New Mutex()
    End Sub

    Public Sub initial(ByRef name As String, ByRef config As configParser)
        assert(Not isemptystring(caseConfigNaming), "should set caseConfigNaming before initial.")
        assert(Not isemptystring(filterConfigNaming), "should set filterConfigNaming before initial.")
        assert(Not isemptystring(multimatchConfigNaming), "should set multimatchConfigNaming before initial.")

        copy(Me.name, name)
        Me.config = New pointer(Of configParser)(config)

        multimatch = configParameter(multimatchConfigNaming, multimatch)
        configlist(caseConfigNaming, casenames)
        configlist(filterConfigNaming, filters)
        If casenames.size() <> filters.size() Then
            raiseError("do not get same pairs of " + caseConfigNaming + " and " + filterConfigNaming _
                       , errorHandle.errorType.warning)
            Dim lessone As Int64 = min(casenames.size(), filters.size())
            casenames.erase(lessone, casenames.size())
            filters.erase(lessone, filters.size())
        End If

        initial()
    End Sub
End Class
